package com.share.thread;

import java.util.concurrent.atomic.AtomicReference;

/**
 * @desc: 自旋锁
 * @author:caifan
 * @date:2022/3/17
 */
public class ReentrantSpinLock {
    private AtomicReference<Thread> owner = new AtomicReference<>();
    // 重入次数
    private int count = 0;

    public void lock() {
        Thread thread = Thread.currentThread();
        if (thread == owner.get()) {
            ++count;
            return;
        }

        //自旋锁获取
        while (!owner.compareAndSet(null, thread)) {
            System.out.println(thread.getName() + "自旋了");
        }
    }

    public void unlock() {
        Thread thread = Thread.currentThread();
        // 持有锁的线程才能解锁
        if (thread == owner.get()) {
            if (count > 0) {
                --count;
            } else {
                // 无需CAS操作，没有竞争，只有线程持有者才能解锁
                owner.set(null);
            }
        }
    }

    public static void main(String[] args) {
        ReentrantSpinLock spinLock = new ReentrantSpinLock();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "开始尝试获取自旋锁");
                spinLock.lock();
                try {
                    System.out.println(Thread.currentThread().getName() + "获取到了自旋锁");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    spinLock.unlock();
                    System.out.println(Thread.currentThread().getName() + "释放了自旋锁");
                }
            }
        };

        Thread t1 = new Thread(runnable);
        Thread t2 = new Thread(runnable);
        t1.start();
        t2.start();
    }
}
